package com.meepo.basic.components.listfragment

import android.os.Bundle
import android.view.View
import androidx.annotation.CallSuper
import androidx.annotation.LayoutRes
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.ethanhua.skeleton.Skeleton
import com.ethanhua.skeleton.SkeletonScreen
import com.meepo.basic.R
import com.meepo.basic.components.view.MeepoFragment
import com.meepo.basic.schema.common.PageResult
import com.meepo.basic.schema.common.ResponseWrapper
import com.meepo.framework.design.recycler.ViewHolder
import com.scwang.smart.refresh.layout.api.RefreshLayout
import com.scwang.smart.refresh.layout.listener.OnRefreshLoadMoreListener
import com.xiaojinzi.component.support.ParameterSupport
import io.reactivex.Observable
import kotlinx.android.synthetic.main.list_fragment.*

abstract class MeepoListFragment<T> : MeepoFragment() {

    protected val argumentName = "listFragmentParams"

    private lateinit var mListAdapter: ListAdapter<T>

    private var mSkeletonScreen: SkeletonScreen? = null

    private var currentPage = 1

    override fun initData() {
        refresh()
    }

    // 刷新数据
    private fun refresh() {
        presenter.call(
            loadDataObservable(),
            { rsp -> onPullRefreshComplete(rsp.data); },
            { onPullRefreshComplete(null, false) }
        )
    }

    private fun onPullRefreshComplete(result: PageResult<T>?, success: Boolean = true) {
        val params = ParameterSupport.getSerializable(arguments, argumentName) ?: ListFragmentParams()

        mSkeletonScreen?.hide()

        if (!success) {
            refresh_layout?.finishRefresh(params.pullRefreshDelay, false, false)

            stateful_layout.showNoNetwork()
            return
        }

        currentPage += 1

        result?.items?.let {
            stateful_layout.showContent()

            mListAdapter.refresh(it)

            refresh_layout?.finishRefresh(params.pullRefreshDelay, true, !result.pagination.hasMore)
            return
        }

//        if (firstRefresh) {
        stateful_layout.showEmpty()
//            firstRefresh = false
//        }

        refresh_layout?.finishRefresh(params.pullRefreshDelay, true, true)
    }


    // 拉取更多数据
    private fun onLoadMore() {
        presenter.call(
            loadDataObservable(currentPage),
            { rsp -> onLoadMoreComplete(rsp.data); },
            { onLoadMoreComplete(null, false) }
        )
    }

    private fun onLoadMoreComplete(result: PageResult<T>?, success: Boolean = true) {

        val params = ParameterSupport.getSerializable(requireArguments(), argumentName) ?: ListFragmentParams()

        if (!success) {
            // 接口错误
            refresh_layout?.finishLoadMore(params.loadMoreDelay, false, false)

            return
        }

        currentPage += 1

        result?.items?.let {
            mListAdapter.addMore(it)

            refresh_layout?.finishLoadMore(params.loadMoreDelay, true, !result.pagination.hasMore)
            return
        }

        // 没有更多
        refresh_layout?.finishLoadMore(params.loadMoreDelay, true, true)
    }


    abstract fun loadDataObservable(page: Int = 1): Observable<ResponseWrapper<PageResult<T>>>

    @CallSuper
    override fun initView(view: View, savedInstanceState: Bundle?) {

        val params = ParameterSupport.getSerializable(arguments, argumentName) ?: ListFragmentParams()

        mListAdapter = ListAdapter(
            this.requireContext(),
            bindFunc = { item, holder, position -> bind(item, holder, position) },
            getLayoutIdFunc = { item, position -> getItemViewLayoutId(item, position) }
        )

        item_recycler_view.adapter = mListAdapter
        item_recycler_view.layoutManager = LinearLayoutManager(this.requireContext())
        item_recycler_view.itemAnimator = null // 取消更新闪烁

        // 骨架屏
        mSkeletonScreen = Skeleton.bind(item_recycler_view)
            .adapter(mListAdapter)
            .shimmer(true)
            .angle(20)
            .frozen(false)
            .duration(1200)
            .load(getItemSkeletonViewLayoutId())
            .count(10)
            .show()

        refresh_layout.setReboundDuration(params.reboundDuration)
        refresh_layout.setEnableRefresh(params.enablePullRefresh)
        refresh_layout.setOnRefreshLoadMoreListener(object : OnRefreshLoadMoreListener {
            override fun onLoadMore(refreshLayout: RefreshLayout) {
                onLoadMore()
            }

            override fun onRefresh(refreshLayout: RefreshLayout) {
                refresh()
            }
        })

        stateful_layout.setOnRetryClickListener {
            refresh()
        }
    }

    override fun setUpContentLayout(): Int = R.layout.list_fragment

    public fun insert(item: T, position: Int = 0) {
        mListAdapter.insert(item, position)
        stateful_layout.showContent()
    }

    protected fun replace(position: Int, newItem: T) {
        mListAdapter.replace(position, newItem)
    }

    protected fun remove(position: Int, adapterPosition: Int) {
        mListAdapter.remove(position, adapterPosition)
    }

    protected fun getRecyclerView(): RecyclerView {
        return item_recycler_view
    }

    // 数据展示方式
    abstract fun bind(item: T, holder: ViewHolder, position: Int)

    // 数据展示 layout
    @LayoutRes
    abstract fun getItemViewLayoutId(item: T, position: Int): Int

    @LayoutRes
    open fun getItemSkeletonViewLayoutId(): Int = R.layout.default_item_skeleton_layout
}